package cn.wyl.basic.service.impl;

import cn.wyl.basic.exception.BusinessException;
import cn.wyl.basic.service.VerifyService;
import cn.wyl.basic.util.SendMsgUtil;
import cn.wyl.basic.util.StrUtils;
import cn.wyl.basic.util.VerifyCodeConstants;
import cn.wyl.basic.util.VerifyCodeUtils;
import cn.wyl.user.domain.User;
import cn.wyl.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyServiceImpl implements VerifyService {
    //要用redis存数据，所以需要RedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Override
    public String getImgCode(String key) {
        //判断key uuid是否为空
        if (StringUtils.isEmpty(key)){
            throw new BusinessException("key为空");
        }

        //获取随机验证码
        String code = VerifyCodeUtils.generateVerifyCode(4);

        //将验证码存放到redis，设置5分钟过期
      /*  set(      K k,                                             key
                    V v,                                             value
                    long l,                                          过期数字
                    java.util.concurrent.TimeUnit timeUnit)          过期时间单位
      */
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);

        //把验证码的值合并到图片，使用Base64编码。并返回base64编码的字符串
        return  VerifyCodeUtils.verifyCode(100,40,code);

    }

    @Override
    public void sendSmsCode(Map<String, Object> paramMap) {
        //1.校验 - 空值校验
        //2.校验 - 图片验证码校验
        //2.1.图片验证码是否过期
        //2.2.图片验证码是否正确
        //3.校验 - 手机号是否被注册 - 查询t_user表
        //4.判断原来的验证码是否有效【3分钟过期 - redis】，从redis是否能拿到通过key【register:18708146200】
        //4.1.如果拿到了，表示有效,继续判断是否过了1分钟重发时间 value【9527:14688777777711】
        //4.1.1.如果没有过，就不应该再发，提示错误 - 请勿重发验证码
        //4.1.2.如果过了，就使用上次的验证码，但是要刷新过期时间【重新添加resis，用新的时间戳】
        //4.2.如果没有拿到，表示验证码过期了
        //4.2.1.重新生成验证码，并添加到redis
        //5.调用短信接口发送短信

        
        /*param = {
                phone: this.phoneUserForm.phone,
                imageCode: this.phoneUserForm.imageCode,
                //从localStorage中获取key：phoneRegisterCodeKey
                imageCodeKey: localStorage.getItem("phoneRegisterCodeKey")
                };
           返回axiousresult （msg）
         */
        //1.校验 - 空值校验
        String phone = (String)paramMap.get("phone");
        String imageCode = (String)paramMap.get("imageCode");
        String imageCodeKey = (String)paramMap.get("imageCodeKey");

        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }
        if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("图片验证码不能为空");
        }
        if(StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请刷新页面重新获取图片验证码");
        }

        //2.校验 - 图片验证码校验
        //2.1.图片验证码是否过期
        Object imageCodeValue = redisTemplate.opsForValue().get(imageCodeKey);
        if(imageCodeValue == null ){
            throw new BusinessException("图片验证码过期(5min有效期)，请重新输入");
        }
        //2.2.图片验证码是否正确
        if(!imageCodeValue.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("错误的图片验证码，请重新输入");
        }

        //3.校验 - 手机号是否被注册
        User user = userMapper.loadByPhone(phone);
        if(user != null){
            throw new BusinessException("该手机已经注册，请直接登录!");
        }

        //redis存值格式：key[register:18708146200] : value[code:time]
        Object codeObj = redisTemplate.opsForValue().get(VerifyCodeConstants.REGISTER_CODE_PREFIX + phone);
        String code = null;
        if(codeObj != null){//没有过期
            String codeStr = (String)codeObj;
            String time = codeStr.split(":")[1];
            long intervalTime = System.currentTimeMillis() - Long.valueOf(time);
            if(intervalTime <= 1*60*1000){ //没过重发时间
                throw new BusinessException("请勿重复发送!");
            }else{
                code = codeStr.split(":")[0];
            }
        }else{//过期了或第一次
            code = StrUtils.getComplexRandomString(4);
        }
        //将验证码数据添加到redis
        redisTemplate.opsForValue().set(VerifyCodeConstants.REGISTER_CODE_PREFIX + phone,
                code + ":" + System.currentTimeMillis(),3, TimeUnit.MINUTES);//存3分钟
        //发短信
        //SendMsgUtil.sendMsg(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");//可以这样测试

    }

    /**
     * 前端绑定微信发送手机验证码
     * @param paramMap
     */
    @Override
    public void binderSmsCode(Map<String, Object> paramMap) {
        //1.校验 - 空值校验
        String phone = (String)paramMap.get("phone");


        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }



        //获取手机验证码 - 判断是否过期  value 9527:1233555555
        //redis存值格式：key[binder:18708146200] : value[code:time]
        Object redisSmsCode = redisTemplate.opsForValue().get(VerifyCodeConstants.BINDER_PREFIX + phone);
        String code = null;
        if (redisSmsCode==null){//第一次发送 or 手机验证码过期了
            //过期了就用新的验证码
            code = StrUtils.getComplexRandomString(6);

        }else{//没有过期
            //验证是否过了重发时间
            //以前保存的时间
            long redisTime = Long.parseLong(redisSmsCode.toString().split(":")[1]);
            //现在的时间
            long nowTime = System.currentTimeMillis();
            //6.没有过期 - 判断是否过了重发时间
            if((nowTime-redisTime)<1*60*1000){//没有过重发时间
                throw new BusinessException("请勿重复获取验证码!!!");
            }else{
                //没有过期就用以前的验证码
                code = redisSmsCode.toString().split(":")[0];
            }
        }

        //将验证码存入redis：【binder:18725556563 - 9527:1233555555】
        //刷新了过期时间
        redisTemplate.opsForValue().set(VerifyCodeConstants.BINDER_PREFIX + phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //发短信
        //SendMsgUtil.sendMsg(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");//可以这样测试

    }
}
